package com.bjc.ws;

import com.bjc.interceptor.UserInterceptor;
import com.bjc.pojo.Message;
import com.bjc.utils.MessageUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
//声明资源路径
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfigurator.class)
@Component
public class ChatEndPoint {
    /**
     * 用线程安全的map来保存当前用户
     */
    private static Map<String,ChatEndPoint> onLineUsers = new ConcurrentHashMap<>();
    /**
     * 声明一个session对象，通过该对象可以发送消息给指定用户，不能设置为静态，每个ChatEndPoint有一个session才能区分.(websocket的session)
     */
    private Session session;
    /**
     * 保存当前登录浏览器的用户，我们之前在HttpSession对象中存储了用户名
     */
    private HttpSession httpSession;

    /**
     * 建立连接时被调用
     *
     * @param session
     * @param config
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        //将局部的session对象赋值给成员session
        this.session = session;
        //获取httpSession对象
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        this.httpSession = httpSession;
        //从httpSession对象中获取用户名
        String username = (String) httpSession.getAttribute("user");
        log.info("上线用户名称：" + username);
        //将对象存储到容器中
        onLineUsers.put(username, this);
        //将当前在线用户的用户名推送给所有的客户端
        //1.获取消息
        String message = MessageUtils.getMessage(true, null, getNames());
        //2.调用方法进行系统消息的推送
        broadcastAllUsers(message);
    }

    /**
     * 获取当前登录的用户
     * @return
     */
    private Set<String> getNames(){
        return onLineUsers.keySet();
    }

    /**
     * 发送系统消息
     * @param message
     */
    private void broadcastAllUsers(String message){
        try{
            //将该消息推送给所有客户端
            Set<String> names = onLineUsers.keySet();
            for(String name : names){
                ChatEndPoint chatEndPoint = onLineUsers.get(name);
                chatEndPoint.session.getBasicRemote().sendText(message);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 接收到客户端发送的数据时被调用
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message,Session session){
        try{
            //将message转换成message对象
            ObjectMapper mapper = new ObjectMapper();
            Message mess = mapper.readValue(message,Message.class);
            //获取将要接收消息的用户
            String toName = mess.getToName();
            //获取消息内容
            String data = mess.getMessage();
            //获取当前登陆用户
            String username = (String) httpSession.getAttribute("user");
            log.info(username + "向"+toName+"发送的消息：" + data);
            //获取推送欸指定用户的消息格式的数据
            String resultMessage = MessageUtils.getMessage(false,username,data);
            if(StringUtils.hasLength(toName)) {
                //发送数据
                onLineUsers.get(toName).session.getBasicRemote().sendText(resultMessage);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 用户断开连接的断后操作
     * @param session
     */
    @OnClose
    public void onClose(Session session){
        String username = (String) httpSession.getAttribute("user");
        log.info("离线用户："+ username);
        if (username != null){
            //从容器中删除指定的用户
            onLineUsers.remove(username);
            UserInterceptor.onLineUsers.remove(username);
        }
        //删除session中存储的信息
        httpSession.removeAttribute("user");
        //获取推送的消息
        String message = MessageUtils.getMessage(true,null,getNames());
        broadcastAllUsers(message);
    }
}
